<?php
/**
 * 用于处理图片常用操作,如:生成缩略图,图片水印生成等
 *
 * @author Mo yi <root@imoi.cn>
 * @link   http://www.imoi.cn
 * @copyright Copyright &copy; 2010-2012 DuoLam Software LLC
 * @license http://www.imoi.cn/license/
 * @version $Id: dpImage.php 2799 2012-04-04 13:35:54Z Mo.yi $
 * @package web.helper
 * @since 1.0
 */

class dpImage
{

    /**
     * 原图片路径,该图片在验证码时指背景图片,在水印图片时指水印图片.
     *
     * @var string
     */
    public $imageUrl;

    /**
     * 字体名称
     *
     * @var sting
     */
    public $fontName;

    /**
     * 字体大小
     *
     * @var integer
     */
    public $fontSize;

    /**
     * 图片实例化名称
     *
     * @var object
     */
    protected $image;

    /**
     * 图象宽度
     *
     * @var integer
     */
    protected $width;

    /**
     * 图象高度
     *
     * @var integer
     */
    protected $height;

    /**
     * 图片格式, 如:jpeg, gif, png
     *
     * @var string
     */
    protected $type;

    /**
     * 文字的横坐标
     *
     * @var integer
     */
    public $fontX;

    /**
     * 文字的纵坐标
     *
     * @var integer
     */
    public $fontY;

    /**
     * 字体颜色
     *
     * @var string
     */
    protected $fontColor;

    /**
     * 生成水印图片的原始图片的宽度
     *
     * @var integer
     */
    protected $imageWidth;

    /**
     * 生成水印图片的原始图片的高度
     *
     * @var integer
     */
    protected $imageHeight;

    /**
     * 生成缩略图的实际宽度
     *
     * @var integer
     */
    protected $widthNew;

    /**
     * 生成缩略图的实际高度
     *
     * @var integer
     */
    protected $heightNew;

    /**
     * 水印图片的实例化对象
     *
     * @var object
     */
    protected $waterImage;

    /**
     * 生成水印区域的横坐标
     *
     * @var integer
     */
    protected $waterX;

    /**
     * 生成水印区域的纵坐标
     *
     * @var integer
     */
    protected $waterY;

    /**
     * 生成水印图片的水印区域的透明度
     *
     * @var integer
     */
    protected $alpha;

    /**
     * 文字水印字符内容
     *
     * @var string
     */
    protected $textContent;

    /**
     * 水印图片的宽度
     *
     * @var integer
     */
    protected $waterWidth;

    /**
     * 水印图片的高度
     *
     * @var integer
     */
    protected $waterHeight;

    /**
     * 构造函数
     *
     * @access public
     * @return boolean
     */
    public function __construct()
	{
        $this->fontSize = 14;
        $this->fontName = DP_PATH . '/web/util/font/aispec.ttf';
    }

	 /**
     * 验证码的判断
     *
     * @param string $code    待验证的验证码内容
     * @return boolean
     */
    public static function checkVerify($sessionName, $code)
	{
		if (empty($sessionName) or empty($code)) return false;
        $code = strtolower($code);
        if (!isset($_SESSION)) session_start();
        return (isset($_SESSION[$sessionName]) && (strtolower($_SESSION[$sessionName]) == $code)) ? true : false;
    }

    /**
     * 显示验证码.
     *
     * @access public
     * @param int $width  验证码宽度
	 * @param int $height 验证码高度
	 * @param int $size   文字大小
	 * @param string $sessionName 存放验证码session名
     * @return void
     */
    public static function verifyCode($width=80, $height=30, $size=16, $sessionName = 'code')
	{
        if (!isset($_SESSION)) session_start();
        $image = (!function_exists('imagecreatetruecolor')) ? 
						imagecreate($width, $height) : 
						imagecreatetruecolor($width, $height);
		$bg_color_array = array(255, 255, 255);
		$back_color     = imagecolorallocate($image, $bg_color_array[0], $bg_color_array[1], $bg_color_array[2]);
		imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $back_color);

		$border_color   = imagecolorallocate($image, 238, 238, 238);
		imagerectangle($image, 0, 0, $width - 1, $height - 1, $border_color);

		$char = 'abcdefghijklmnopqrstuvwxyz0123456789';
		$num1 = $char[mt_rand(0, 23)];
		$num2 = $char[mt_rand(0, 23)];
		$num3 = $char[mt_rand(0, 23)];
		$num4 = $char[mt_rand(0, 23)];
		$text = $num1 . $num2 . $num3 . $num4;

		$font_name    = DP_PATH . '/web/util/font/aispec.ttf';

		$code_strlen = strlen($text);
		$per_width   = ceil(($width - 10) / $code_strlen);

		for ($i = 0; $i < $code_strlen; $i ++) {
			$text_content = $text[$i];
			$bbox         = imagettfbbox($size, 0, $font_name, $text_content);
			$font_w       = $bbox[2]-$bbox[0];
			$font_h       = abs($bbox[7]-$bbox[1]);

			$font_x       = ceil(($per_width - $font_w) / 2) + $per_width * $i + 5;
			$min_y        = $font_h + 5;
			$max_y        = $height - 5;
			$font_y       = rand($min_y, $max_y);

			$font_color   = imagecolorallocate($image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
			imagettftext($image, $size, 0, $font_x, $font_y, $font_color, $font_name, $text_content);
		}

        for ($i = 0; $i < 5; $i ++) {
            $line_color = imagecolorallocate($image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            imageline($image, mt_rand(2, $width - 3), mt_rand(2, $height  - 3), mt_rand(2, $width  - 3), mt_rand(2, $height  - 3), $line_color);
        }

        $_SESSION[$sessionName] = $text;

        if (headers_sent()) {
            dpException::error('在header()函数前有向页面输出结果，dpImage');
        }

        header('Content-type:image/png');
        imagepng($image);
        imagedestroy($image);
    }

    /**
     * 初始化运行环境,获取图片格式并实例化.
     *
     * @param string $url 图片路径
     * @return boolean
     */
    protected function parseImageInfo($url)
	{
        list($this->imageWidth, $this->imageHeight, $type) = getimagesize($url);

        switch ($type) {
            case 1:
                $this->image = imagecreatefromgif($url);
                $this->type  = 'gif';
                break;

            case 2:
                $this->image = imagecreatefromjpeg($url);
                $this->type  = 'jpg';
                break;

            case 3:
                $this->image = imagecreatefrompng($url);
                $this->type  = 'png';
                break;

            case 4:
                $this->image = imagecreatefromwbmp($url);
                $this->type  = 'bmp';
                break;
        }
        return true;
    }

    /**
     * 设置字体名称.
     *
     * @param sting $name    字体名称(字体的路径)
     * @param integer $size    字体大小
     */
    public function setFont($name, $size = null)
	{
        if (!empty($name)) $this->fontName = $name;
        if (!is_null($size)) $this->fontSize = (int)$size;
        return $this;
    }

    /**
     * 设置字体大小.
     *
     * @param integer $size    字体大小
     * @return $this
     */
    public function setFonSize($size)
	{
        if (!empty($size)) $this->fontSize = intval($size);
        return $this;
    }

    /**
     * 获取颜色参数.
     *
     * @param integer $x    RGB色彩中的R的数值
     * @param integer $y    RGB色彩中的G的数值
     * @param integer $z    RGB色彩中的B的数值
     * @return $this
     */
    public function setFontColor($x=false, $y=false, $z=false)
	{
        $this->fontColor = (is_int($x) && is_int($y) && is_int($z)) ? array($x, $y, $z) : array(255, 255, 255);
        return $this;
    }

    /**
     * 水印图片的URL.
     *
     * @param string $url    图片的路径(图片的实际地址)
     * @return $this
     */
    public function setImageUrl($url)
	{
        if (!empty($url)) $this->imageUrl = $url;
        return $this;
    }

    /**
     * 设置生成图片的大小.
     *
     * @param integer $width    图片的宽度
     * @param integer $height    图片的高度
     * @return $this
     */
    public function setImageSize($width, $height)
	{
        if (!empty($width)) $this->width = (int)$width;
        if (!empty($height)) $this->height = (int)$height;
        return $this;
    }

    /**
     * 设置文字水印字符串内容.
     *
     * @param string $content
     * @return $this
     */
    public function setTextContent($content)
	{
        if (!empty($content)) $this->textContent = $content;
        return $this;
    }

    /**
     * 设置水印图片水印区域的透明度.
     *
     * @param integer $param    水印区域的透明度
     * @return $this
     */
    public function setWatermarkAlpha($param)
	{
        if (!empty($param)) $this->alpha = intval($param);
        return $this;
    }

    /**
     * 调整文字水印区域的位置
     *
     * @return boolean
     */
    protected function handleWatermarkFontPlace($limit_option = false)
	{
        if (!$this->fontX || !$this->fontY) {
            if (!$this->textContent) $this->textContent = 'DuoLamPHP';

            $bbox = imagettfbbox($this->fontSize, 0, $this->fontName, $this->textContent);

            //文字margin_right为5px,特此加5
            $font_w = $bbox[2] - $bbox[0] + 5;
            $font_h = abs($bbox[7] - $bbox[1]);

            if ($limit_option === true && $this->heightNew && $this->heightNew) {
				$this->fontX = ($this->widthNew > $font_w) ? $this->widthNew - $font_w : 0;
				$this->fontY = ($this->heightNew > $font_h) ? $this->heightNew - $font_h : 0;
            } else {
                $this->fontX = ($this->imageWidth > $font_w) ? $this->imageWidth - $font_w : 0;
                $this->fontY = ($this->imageHeight > $font_h) ? $this->imageHeight - $font_h : 0;
            }
        }
        return true;
    }

    /**
     * 常设置的文字颜色转换为图片信息.
     *
     * @return boolean
     */
    protected function handleFontColor()
	{
        if (empty($this->fontColor)) $this->fontColor = array(255, 255, 255);
        return imagecolorallocate($this->image, $this->fontColor[0], $this->fontColor[1], $this->fontColor[2]);
    }

    /**
     * 根据图片原来的宽和高的比例,自适应性处理缩略图的宽度和高度
     *
     * @return boolean
     */
    protected function handleImageSize()
	{
        //当没有所生成的图片的宽度和高度设置时.
        if (!$this->width || !$this->height) {
            dpException::error('要生成的图片没有宽度和高度，'.get_class($this));
        }

        $per_w = $this->width/$this->imageWidth;
        $per_h = $this->height/$this->imageHeight;

        if (ceil($this->imageHeight*$per_w)>$this->height) {
            $this->widthNew  = ceil($this->imageWidth*$per_h);
            $this->heightNew = $this->height;
        } else {
            $this->widthNew  = $this->width;
            $this->heightNew = ceil($this->imageHeight*$per_w);
        }
        return true;
    }

    /**
     * 生成图片的缩略图.
     *
     * @param string $url            原始图片路径
     * @param string $dist_name     生成图片的路径(注:无须后缀名)
     * @return boolean
     */
    public function makeLimitImage($url, $dist_name = null)
	{
        if (!$url) return false;
 
        //原图片分析.
        $this->parseImageInfo($url);
        $this->handleImageSize();

        //新图片分析.
        $image_dist = imagecreatetruecolor($this->widthNew, $this->heightNew);

        //生成新图片.
        imagecopyresampled($image_dist, $this->image, 0, 0, 0, 0, $this->widthNew, $this->heightNew, $this->imageWidth, $this->imageHeight);

        $this->createImage($image_dist, $dist_name, $this->type);
        imagedestroy($image_dist);
        imagedestroy($this->image);

        return true;
    }

    /**
     * 生成目标图片.
     *
     * @param string $image_dist    原始图片的路径
     * @param string $dist_name        生成图片的路径
     * @param string $image_type    图片格式
     */
    protected function createImage($image_dist, $dist_name = null, $image_type)
	{
        if (!$image_dist || !$image_type) return false;

        if (!is_null($dist_name)) {
            switch ($image_type) {
                case 'gif':
                    imagegif ($image_dist, $dist_name.'.gif', 95);
                    break;

                case 'jpg':
                    imagejpeg($image_dist, $dist_name.'.jpg', 95);
                    break;

                case 'png':
                    imagepng($image_dist, $dist_name.'.png', 95);
                    break;

                case 'bmp':
                    imagewbmp($image_dist, $dist_name.'.bmp', 95);
                    break;
            }
        } else {
            switch ($image_type) {
                case 'gif':
                    header('Content-type:image/gif', 95);
                    imagegif ($image_dist);
                    break;

                case 'jpg':
                    header('Content-type:image/jpeg', 95);
                    imagejpeg($image_dist);
                    break;

                case 'png':
                    header('Content-type:image/png', 95);
                    imagepng($image_dist);
                    break;

                case 'bmp':
                    header('Content-type:image/png', 95);
                    imagewbmp($image_dist);
                    break;
            }
        }
        return true;
    }

    /**
     * 生成文字水印图片.
     *
     * @param stirng $image_url    背景图片的路径
     * @param string $dist_name    路径目标图片的
     * @return boolean
     */
    public function makeTextWatermark($image_url, $dist_name = null)
	{
        if (!$image_url) return false;

        //分析原图片.
        $this->parseImageInfo($image_url);

        //当所要生成的文字水印图片有大小尺寸限制时(缩略图功能)
        if ($this->width && $this->height) {
            $this->handleImageSize();
            //新图片分析.
            $image_dist = imagecreatetruecolor($this->widthNew, $this->heightNew);

            //生成新图片.
            imagecopyresampled($image_dist, $this->image, 0, 0, 0, 0, $this->widthNew, $this->heightNew, $this->imageWidth, $this->imageHeight);

            //所生成的图片进行分析.
            $this->handleWatermarkFontPlace(true);

            $font_color = $this->handleFontColor();

            //生成新图片.
            imagettftext($image_dist, $this->fontSize, 0, $this->fontX, $this->fontY, $font_color, $this->fontName, $this->textContent);
            $this->createImage($image_dist, $dist_name, $this->type);
            imagedestroy($image_dist);
        } else {
            //所生成的图片进行分析.
            $this->handleWatermarkFontPlace();
            $font_color = $this->handleFontColor();

            //生成新图片.
            imagettftext($this->image, $this->fontSize, 0, $this->fontX, $this->fontY, $font_color, $this->fontName, $this->textContent);
            $this->create_image($this->image, $dist_name, $this->type);
        }
        imagedestroy($this->image);

        return true;
    }

    /**
     * 获取水印图片信息
     *
     * @return boolean
     */
    protected function handleWatermarkImage()
	{
        if ($this->image && !$this->waterImage) {
            $water_url = empty($this->imageUrl) ? DP_PATH . '/web/util/font/' . 'watermark.' . $this->type : $this->imageUrl;
            list($this->waterWidth, $this->waterHeight, $type) = getimagesize($water_url);
            switch ($type) {
                case 1:
                    $this->waterImage = imagecreatefromgif ($water_url);
                    break;

                case 2:
                    $this->waterImage = imagecreatefromjpeg($water_url);
                    break;

                case 3:
                    $this->waterImage = imagecreatefrompng($water_url);
                    break;

                case 4:
                    $this->waterImage = imagecreatefromwbmp($water_url);
                    break;
            }
        }
        return true;
    }

    /**
     * 调整水印区域的位置,默认位置距图片右下角边沿5像素.
     *
     * @return boolean
     */
    protected function handleWatermarkImagePlace($pos = 0)
	{
        $width  = $this->widthNew ? $this->widthNew : $this->imageWidth;
        $height = $this->heightNew ? $this->heightNew : $this->imageHeight;
        // 水印位置
        switch ($pos) {
            case 1://1为顶端居左
                $this->waterX = 5;
                $this->waterY = 5;
                break;
            case 2://2为顶端居中
                $this->waterX = ($width - $this->waterWidth) / 2;
                $this->waterY = 5;
                break;
            case 3://3为顶端居右
                $this->waterX = $width  - $this->waterWidth - 5;
                $this->waterY = 5;
                break;
            case 4://4为中部居左
                $this->waterX = 5;
                $this->waterY = ($height - $this->waterHeight) / 2;
                break;
            case 5://5为中部居中
                $this->waterX = ($width  - $this->waterWidth) / 2;
                $this->waterY = ($height - $this->waterHeight) / 2;
                break;
            case 6://6为中部居右
                $this->waterX = $width   - $this->waterWidth - 5;
                $this->waterY = ($height - $this->waterHeight) / 2;
                break;
            case 7://7为底端居左
                $this->waterX = 5;
                $this->waterY = $height - $this->waterHeight - 5;
                break;
            case 8://8为底端居中
                $this->waterX = ($width - $this->waterWidth) / 2;
                $this->waterY = $height - $this->waterHeight - 5;
                break;
            case 9://9为底端居右
                $this->waterX = $width  - $this->waterWidth - 5;
                $this->waterY = $height - $this->waterHeight - 5;
                break;
            default: //随机
                $this->waterX = rand(0, ($width  - $this->waterWidth));
                $this->waterY = rand(0, ($height - $this->waterHeight));
                break;
        }
        
        return true;
    }

    /**
     * 生成图片水印.
     *
     * @param string $image_url    原始图片的路径
     * @param string $dist_name 生成图片的路径(注:不含图片后缀名)
     * @return boolean
     */
    public function makeImageWatermark($image_url, $dist_name = null, $pos = 0)
	{
        if (!$image_url) return false;

        //分析图片信息.
        $this->parseImageInfo($image_url);

        //水印图片的透明度参数
        $this->alpha = empty($this->alpha) ? 85 : $this->alpha;

        //对水印图片进行信息分析.
        $this->handleWatermarkImage();

        if ($this->width && $this->height) {
            $this->handleImageSize();
            //新图片分析.
            $image_dist = imagecreatetruecolor($this->widthNew, $this->heightNew);

            //生成新图片.
            imagecopyresampled($image_dist, $this->image, 0, 0, 0, 0, $this->widthNew, $this->heightNew, $this->imageWidth, $this->imageHeight);

            //分析新图片的水印位置.
            $this->handleWatermarkImagePlace($pos);

            //生成新图片.
            imagecopymerge($image_dist, $this->waterImage, $this->waterX, $this->waterY, 0, 0, $this->waterWidth, $this->waterHeight, $this->alpha);
            $this->createImage($image_dist, $dist_name, $this->type);
            imagedestroy($image_dist);
        } else {
            //分析新图片的水印位置.
            $this->handleWatermarkImagePlace($pos);

            //生成新图片.
            imagecopymerge($this->image, $this->waterImage, $this->waterX, $this->waterY, 0, 0, $this->waterWidth, $this->waterHeight, $this->alpha);
            $this->createImage($this->image, $dist_name, $this->type);
        }

        imagedestroy($this->image);
        imagedestroy($this->waterImage);

        return true;
    }

    /**
     * 裁切图片
     */
    public function cropImage($image_url, $dist_name, $config = array())
    {
        if (!$image_url) return false;

        //分析图片信息.
        $this->parseImageInfo($image_url);

        //新图片分析.
        $image_dist = imagecreatetruecolor($config['width'], $config['height']);

        //生成新图片.
        imagecopyresampled(
            $image_dist, $this->image, 0, 0,
            $config['x'], $config['y'], $config['width'], $config['height'],
            $config['width'], $config['height']
        );
        $this->createImage($image_dist, $dist_name, $this->type);
        imagedestroy($image_dist);
        return true;
    }
}